package com.amiu.autoMybatis;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.stereotype.Component;

import com.amiu.autoMybatis.annotation.Mapper;
import com.amiu.autoMybatis.test.mapper.DaoMapper;

/**
 * 
 * @author amiu
 * @version createtime：2017-8-31 下午3:01:59
 */
//@Component
public class SqlSessionsHelperFail {
	private static final Logger logger = Logger.getLogger(SqlSessionsHelperFail.class);
	private MybatisInitialization init = new MybatisInitialization();
	private SqlSessionFactory sqlSessionFactory;
	private SqlSession sqlSession;
	/**
	 * 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用，
	 * 它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession
	 * 实例的引用放在一个类的静态字段或实例字段中。
	 * 所以threadSqlSession不能是static的
	 * threadSqlSession要把新进的sqlsession加入，要删除close的sqlsession，所以也不能为final
	 */
	/**
	 * 2017-10-17
	 * 我现在认为SqlSession应该单独写一个SqlsessionHelper
	 * sqlSessionFactory获取不同实例的SqlSession
	 * SqlSession再用SqlsessionHelper去统一处理
	 */
	private ThreadLocal<Map<String, SqlSession>> threadSqlSession = new ThreadLocal<Map<String, SqlSession>>();

	private Map<String, SqlSession> setThreadSqlSession() {
		Map<String, SqlSession> mapSession = threadSqlSession.get() ;
		if(mapSession == null){
			mapSession = new HashMap<String, SqlSession>();
			threadSqlSession.set(mapSession);
		}
		return mapSession;
	}

	public SqlSessionsHelperFail(String scanPackage) {
		init.setBaseScanPackage(scanPackage);
	}

	public SqlSessionsHelperFail(String scanPackage, Class<?> annotationClazz) {
		init.setAnnotationClazz(annotationClazz);
		init.setBaseScanPackage(scanPackage);
	}

	public <T> SqlSession openSession(Class<T> clazz) {
		sqlSessionFactory = init.getSqlSessionFactory();

		String mapKey = clazz.getName();
		Map<String, SqlSession> sessionMap = setThreadSqlSession();
		//clazz已经存在
		if (sessionMap.containsKey(mapKey)) {
			return sessionMap.get(mapKey);
		}
		//clazz不存在，new一个session，一个Mybatis的Mapper对应一个session
		sqlSession = sqlSessionFactory.openSession(true);
		
		sessionMap.put(mapKey, sqlSession);
		threadSqlSession.set(sessionMap);
		System.out.println("new sqlsession for " + mapKey);
		return sqlSession;
	}

	public void openSession(boolean autoCommit) {

		sqlSessionFactory.openSession(autoCommit);

	}

	public <T> T getDao(Class<T> clazz) {
		sqlSession = openSession(clazz);
		return sqlSession.getMapper(clazz);
	}

	public SqlSessionsHelperFail(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}

	private List<SqlSession> getAllSession(){
		Map<String, SqlSession> mapSession = threadSqlSession.get();
		List<SqlSession> sqlSessions = null;
		if(!(mapSession == null)){
			sqlSessions = new ArrayList<SqlSession>();
			for (String key: mapSession.keySet()) {
				sqlSessions.add(mapSession.get(key));
			}
		}
		return sqlSessions;
	}
	
	public void commitSessions(){
		List<SqlSession> sqlSessions = getAllSession();
		for (SqlSession sqlSession : sqlSessions) {
			sqlSession.commit();
		}
	}
	
	public void rollbackSessions(){
		List<SqlSession> sqlSessions = getAllSession();
		for (SqlSession sqlSession : sqlSessions) {
			sqlSession.rollback();
		}
	}
	//threadSqlSession是 static final的，关了Session又要重新获取
	public void closeSessions(){
		Map<String, SqlSession> mapSession = threadSqlSession.get();
		for (String key : mapSession.keySet()) {
			mapSession.get(key).commit();
			mapSession.get(key).close();
			mapSession.remove(key);
			threadSqlSession.set(mapSession);
		}
	}
	
	// boolean isNull() {
	// return sqlSession == null;
	// }

	public static void main(String[] args) {
//		SqlSessionsHelper helper = new SqlSessionsHelper(
//				"com.amiu.autoMybatis.mapper");
//		DaoMapper mapper = helper.getDao(DaoMapper.class);
//		DaoMapper mapper2 = helper.getDao(DaoMapper.class);
//		System.out.println(mapper == mapper2);
//		helper.closeSessions();
//		System.out.println("colse session");
//		DaoMapper mapper3 = helper.getDao(DaoMapper.class);
//		DaoMapper mapper4 = helper.getDao(DaoMapper.class);
//		System.out.println(mapper3 == mapper4);
	}

	
}
